<?php
class GuessedPath 
{
	var $path = null;
	function GuessedPath( $path )
	{
		$this->path = $path;
	}
	function basename ()
	{
		
		$tokens = $this->tokens();
		$basename = array_pop( $tokens );
		return $basename;
	}
	function exists ()
	{
		return file_exists( $this->path );
	}
	function extension ()
	{
		if ( !$this->exists() ) return false;
		$basename = $this->basename();
		if ( !$basename ) return '';
		$tokens = explode( '.', $basename );
		if ( count( $tokens ) < 2 ) return '';
		return array_pop( $tokens );
	}	
	
	function tokens ( $trim = false )
	{
		$path = $this->normalized( $trim );
		$tokens = explode( DIRECTORY_SEPARATOR, $path );
		return  $tokens;
	}
	function normalized ()
	{
		return $this->_normalizePath( $this->path );
	}
	function absolute ( $basePath = false )
	{
		if ( $basePath === false ) $basePath = $this->base;
		
		$path = $this->_normalizePath( $this->path );
		if ( substr( $path, 0, 1 ) != DIRECTORY_SEPARATOR )
		{ 
			//relative path, we assume relative to our base directory
			$path = $basePath.DIRECTORY_SEPARATOR.$path;
		}
		return $path;
	}
	function isInside( $stringPath )
	{
		$Parent = $this->_fork( $stringPath );
		if ( !$Parent->exists() ) return false;
		$absoluteParent = $Parent->absolute();
		return ( strpos( $this->absolute(), $absoluteParent ) === 0 );
	}
	/**
	 * Merges with one path before (or after) and returns it as string
	 */
	function merge ( $pathBefore = false  , $pathAfter = false )
	{
		$path = $this->normalized();
		if ( $pathBefore ) $pathBefore = $this->_normalizePath( $pathBefore );
		if ( $pathAfter ) $pathAfter = $this->_normalizePath( $pathAfter );
		If ( $pathBefore )
		{
			$path = $pathBefore.DIRECTORY_SEPARATOR.ltrim( $path, DIRECTORY_SEPARATOR );
		}
		If ( $pathAfter )
		{
			$path = $pathBefore.DIRECTORY_SEPARATOR.$path.ltrim( $pathAfter, DIRECTORY_SEPARATOR );
		}
		return $path;
	}
	/**
	 * subtracts the passed basePath returning the relative path
	 *
	 * @param string $basePath
	 * @return string $relativePath ( FALSE if basePath is not found )
	 */
	function diff ( $basePath )
	{
		$basePath = $this->_fork( $basePath );
		if ( $this->isInside( $basePath->absolute() ))
		{
			return ltrim( str_replace( $basePath->absolute(), '', $this->absolute() ), DIRECTORY_SEPARATOR );	
		}
		return false;
	}
	//------------private functions
	function _normalizePath ( $path )
	{
		if ( DIRECTORY_SEPARATOR != '/' ) $path = str_replace( '/', DIRECTORY_SEPARATOR, $path );
		$path = rtrim( $path, DIRECTORY_SEPARATOR );
		return $path;
	}
	function _fork ( $path )
	{
		$class = get_class( $this );
		return new $class( $path, $this->base );
	}
}

class Path extends GuessedPath 
{
	var $path = null;
	var $base = null;
	var $guess = null;
	
	function Path( $path, $base )
	{
		parent::GuessedPath( $path );
		$this->base = $base;
		$this->guess = new GuessedPath( $path );
	}
	function basename ()
	{
		if ( !$this->exists() ) return false;
		if ( is_dir( $this->path )) return '';
		return basename( $this->path );
	}
	function exists ()
	{
		return file_exists( $this->absolute() );
	}
	function extension ()
	{
		if ( !$this->exists() ) return false;
		$basename = $this->basename();
		if ( !$basename ) return '';
		$tokens = explode( '.', $basename );
		if ( count( $tokens ) < 2 ) return '';
		return array_pop( $tokens );
	}
	
	/**
	 * If path is a dir returns the dir itself.
	 * If is a file returns the parent dir.
	 *
	 */
	function homeDir ()
	{
		if ( !$this->exists() ) return false;
		$path = $this->absolute();
		if ( is_dir( $path )) return $path;
		return dirname( $path );
	}
/*
	function absolute ( $basePath = false )
	{
		if ( $basePath === false ) $basePath = $this->base;
		
		$path = $this->_normalizePath( $this->path );
		if ( substr( $path, 0, 1 ) != DIRECTORY_SEPARATOR )
		{ 
			//relative path, we assume relative to our base directory
			$path = $basePath.DIRECTORY_SEPARATOR.$path;
		}
		return $path;
	}
*/
}

?>